package com.zwh.modules.hzlog.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zwh.common.codec.EncodeUtils;
import com.zwh.common.lang.DateUtils;
import com.zwh.common.utils.excel.ExcelExport;
import com.zwh.common.utils.excel.ExcelImport;
import com.zwh.common.utils.excel.annotation.ExcelField;
import com.zwh.modules.datamax.entity.DataMax;
import com.zwh.modules.hzlog.dto.ContractTotalDto;
import com.zwh.modules.hzlog.entity.TenderImportDto;
import com.zwh.modules.hzlog.entity.WeatherModel;
import com.zwh.modules.hzlog.listener.TenderImportDtoListener;

/**
 * @Author zwh
 * @Date 2019/12/18 19:29
 **/
@Controller
@RequestMapping("/a/test")
public class TestController {
    Logger logger = LoggerFactory.getLogger(TestController.class);
    @Autowired
    ObjectMapper objectMapper;

    @RequestMapping(value = "index")
    @ResponseBody
    public String index(DataMax dataMax) throws JsonProcessingException {
        logger.info("测试log日志运行");
        logger.info(objectMapper.writeValueAsString(dataMax));
        return dataMax.getDataType();
    }


    /**
     * 分页分批查询导出数据
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "testExportForDivide")
    public void testExportForDivide(HttpServletRequest request, HttpServletResponse response) {
        logger.info("分页分批查询导出数据导出开始");
        String fileName = "用户洞察中心App报表.xlsx";
        String sheetName = "用户洞察中心App报表";
        try {
            response.reset();
            response.setContentType("application/octet-stream; charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + EncodeUtils.encodeUrl(fileName));

            OutputStream out = response.getOutputStream();
            //这里指定需要表头，因为model通常包含表信头息
            ExcelWriter writer = EasyExcelFactory.write(out, WeatherModel.class)
                    .excelType(ExcelTypeEnum.XLSX)
                    .autoCloseStream(false).build();
//            .excelType(ExcelTypeEnum.XLSX).needHead(true)
//                    .autoCloseStream(Boolean.FALSE).build()

            //写第一个sheet,数据全是List<String> 无模型映射关系
            int sheetNo = 1;
            WriteSheet sheet = EasyExcelFactory.writerSheet(sheetNo, sheetName).build();
            //设置表格样式

            int pageSize = 50000; // 分5千条一次查询
            int dataLength = 2000001; //假设数据总量为十万条数据
            //一百万数据存储一个sheet
            int remainNumber = dataLength % 1000000;
            int sheetNoSize = dataLength / 1000000;
            if (remainNumber != 0) {
                sheetNoSize++;
            }

            List<WeatherModel> resultList = null;
            Map<String, Object> condition = new HashMap<>();
            boolean isFirst = true;
            int startIndex = 0;

            while (sheetNo <= sheetNoSize) {
                if (isFirst) {
                    isFirst = false;
                } else {
                    //sheet指向下一个sheet
                    sheet = EasyExcelFactory.writerSheet(sheetNo, sheetName + sheetNo).build();
                }

                // 要保证每个sheet页总数据最多为100万条数据
                int sheetMaxDataSize = 1000000;
                // 如果剩余数量不足100万条,设置当前sheet也数据大小为剩余数据大小
                if (sheetNo * sheetMaxDataSize > dataLength) {
                    sheetMaxDataSize = dataLength - ((sheetNo - 1) * sheetMaxDataSize);
                }
                //开始下标，到结束下标
                while (true) {
                    int curDataSize = pageSize;
                    //遍历到当前sheet的行数是否大于最大sheet行数限制
                    int currentSheetRow = startIndex - (sheetNo - 1) * 1000000;
                    if (currentSheetRow + pageSize > sheetMaxDataSize) {
                        //当前sheet超过100万条数据,到下一个sheet页
                        //获取当前要查询的总数据
                        curDataSize = sheetMaxDataSize - currentSheetRow;
                        condition.put("startIndex", startIndex);
                        condition.put("pageSize", curDataSize);
                        if (curDataSize == 0) {
                            break;
                        }
                        //查询指定位置数据列表
                        resultList = queryList(condition);
                        if (resultList != null && !resultList.isEmpty()) {
                            //写数据
                            writer.write(resultList, sheet);
                            break;
                        }
                        //当前sheet最后一次写入数据
                        writer.write(resultList, sheet);
                        //设置当前下标为sheetNo的第一条数据
                        startIndex = sheetNo * 1000000;
                        break;
                    }

                    //当前sheet表可以写入查询数据大小
                    condition.put("startIndex", startIndex);
                    condition.put("pageSize", curDataSize);
                    resultList = queryList(condition);
                    if (resultList != null && !resultList.isEmpty()) {
                        //写数据
                        writer.write(resultList, sheet);
                        break;
                    }
                    startIndex = startIndex + curDataSize;

                    writer.write(resultList, sheet);
                }
                //查询数据为空时，结束循环
                if (resultList == null || resultList.isEmpty()) {
                    break;
                }
                sheetNo++;
            }
            //关闭writer的输出流
            writer.finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private List<WeatherModel> queryList(Map<String, Object> condition) {
        List<WeatherModel> list = new ArrayList<>();
        Integer startIndex = (Integer) condition.get("startIndex");
        Integer pageSize = (Integer) condition.get("pageSize");
        int endIndex = startIndex + pageSize;
        while (startIndex < endIndex) {
            WeatherModel item = new WeatherModel();
            item.setAreaId("areaid" + startIndex);
            item.setNameCn("name" + startIndex);
            item.setNameCn("中文" + startIndex);
            list.add(item);
            startIndex++;
        }
        return list;
    }

    @RequestMapping(value = "testExport")
    public void testExport(HttpServletRequest request, HttpServletResponse response) {
        logger.info("导出开始");
        List<ContractTotalDto> dtoList = new ArrayList<>();
        ContractTotalDto contractTotalDto = new ContractTotalDto();
        contractTotalDto.setContractName("ContractName");
        contractTotalDto.setInterestMoney(100.00123);
        contractTotalDto.setUnSingMoney(0.9951);
        contractTotalDto.setContractRemainMoney(new Date());
        dtoList.add(contractTotalDto);
        String fileName = "合同数据" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";

        try (ExcelExport ee = new ExcelExport("合同数据",
                "合同数据(单位：万元)", ContractTotalDto.class, ExcelField.Type.EXPORT)) {
            ee.setDataList(dtoList).write(response, fileName);
        }
    }

    /**
     * 导入数据
     */
    @ResponseBody
    @PostMapping(value = "importData")
    public List<ContractTotalDto> importData(MultipartFile file, String updateSupport) {
        try (ExcelImport ei = new ExcelImport(file, 2, 0)) {
            List<ContractTotalDto> list = ei.getDataList(ContractTotalDto.class);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * easyExcel导入数据
     */
    @ResponseBody
    @PostMapping(value = "easyExcelImportData")
    public Object easyExcelImportData(MultipartFile file, String updateSupport) {
        ExcelReader excelReader = null;
        try {
            excelReader = EasyExcel.read(file.getInputStream())
                    // 需要读取批注 默认不读取
//                    .extraRead(CellExtraTypeEnum.COMMENT)
                    // 需要读取超链接 默认不读取
//                    .extraRead(CellExtraTypeEnum.HYPERLINK)
                    // 需要读取合并单元格信息 默认不读取
                    .extraRead(CellExtraTypeEnum.MERGE)
                    .build();
            List<TenderImportDto> allData = new ArrayList<>();
            ReadSheet readSheet1 =
                    EasyExcel.readSheet(0).head(TenderImportDto.class)
                            .registerReadListener(new TenderImportDtoListener(allData))
                            .build();
            excelReader.read(readSheet1);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
                excelReader.finish();
            }
        }
        return null;
    }

    @RequestMapping(value = "testExportWord")
    public void testExportWord(HttpServletRequest request, HttpServletResponse response) {
        logger.info("导出开始");
        List<ContractTotalDto> dtoList = new ArrayList<>();
        ContractTotalDto contractTotalDto = new ContractTotalDto();
        contractTotalDto.setContractName("ContractName");
        contractTotalDto.setInterestMoney(100.00123);
        contractTotalDto.setUnSingMoney(0.9951);
        contractTotalDto.setContractRemainMoney(new Date());
        dtoList.add(contractTotalDto);
        String fileName = "合同数据" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx";

        try (ExcelExport ee = new ExcelExport("合同数据",
                "合同数据(单位：万元)", ContractTotalDto.class, ExcelField.Type.EXPORT)) {
            ee.setDataList(dtoList).write(response, fileName);
        }
    }
}
